package com.topnav.mc.admin.service.impl;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.Future;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dtflys.forest.annotation.Var;
import com.js.lib.cache.Cache;
import com.js.lib.result.Result;
import com.topnav.mc.admin.bean.cachebean.CacheDeviceFenceBean;
import com.topnav.mc.admin.controller.FullScreenMoniter.ChartDataBean;
import com.topnav.mc.admin.dao.mapper.*;
import com.topnav.mc.admin.entity.*;
import com.topnav.mc.admin.entity.bean.DeviceAlarmBean;
import com.topnav.mc.admin.entity.bean.DeviceBean;
import com.topnav.mc.admin.entity.bean.GbServerBean;
import com.topnav.mc.admin.entity.bean.LogContentBean;
import com.topnav.mc.admin.entity.enums.DeviceType;
import com.topnav.mc.admin.entity.enums.EnumLogType;
import com.topnav.mc.admin.entity.enums.EnumOperateFunction;
import com.topnav.mc.admin.entity.enums.EnumStreamMode;
import com.topnav.mc.admin.entity.param.DeviceParam;
import com.topnav.mc.admin.entity.param.GbServerParam;
import com.topnav.mc.admin.security.PermissionGrade;
import com.topnav.mc.admin.service.*;
import com.topnav.mc.admin.view.device.IDeviceViewService;
import com.topnav.mc.base.mc.McServiceImpl;
import com.topnav.mc.common.Constant;
//import org.joda.time.LocalDate;
import com.topnav.mc.document.entity.Document;
import com.topnav.mc.document.service.IDocumentService;
import com.topnav.mc.exception.ExceptionMsg;
import com.topnav.mc.gbserverapi.DeviceApi;
import com.topnav.mc.gbserverapi.bean.GbDevice;
import com.topnav.mc.gbserverapi.bean.GbDeviceChannel;
import com.topnav.mc.gbserverapi.bean.UpgradeParam;
import com.topnav.mc.listener.bean.GbDeviceChannelResult;
import com.topnav.mc.task.DeviceUpdateToGbServerTask;
import com.topnav.mc.uitls.ExceptionUtil;
import com.topnav.mc.uitls.GbServerUtil;
import com.topnav.mc.uitls.PermissionGradeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.js.lib.exception.CustomException;

import javax.annotation.Resource;

@Slf4j
@Service
//public class DeviceServiceImpl extends CommServiceImpl<DeviceMapper,Device> implements IDeviceService{
public class DeviceServiceImpl extends McServiceImpl<DeviceMapper,Device, DeviceBean, DeviceParam> implements IDeviceService{
	@Autowired
	private OrganizationMapper organizationMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private GbServerMapper gbServerMapper;
	@Autowired
	private IDeviceChannelService deviceChannelService;
	@Resource(name="sysCache")
	private Cache sysCache;
	@Autowired
	private IDeviceViewService deviceViewService;
	@Autowired
	private IEntityOperateLogService entityOperateLogService;

	@Resource(name="deviceUpdateToGbServerTask")
	private DeviceUpdateToGbServerTask deviceUpdateToGbServerTask;
	@Autowired
	private PermissionGradeUtil permissionGradeUtil;
	@Autowired
	private IGbServerService gbServerService;
	@Autowired
	private IDeviceLogService deviceLogService;
	@Autowired
	private IDocumentService documentService;
	@Autowired
	private IOrganizationService organizationService;
	@Resource
	private DeviceApi deviceApi;
	@Autowired
	private IDeviceOnlineTotalService deviceOnlineTotalService;

	@Autowired
	private IDeviceAlarmService deviceAlarmService;
	@Autowired
	private IFenceAlarmService fenceAlarmService;
	@Autowired
	private IDeviceFavoriteService deviceFavoriteService;
	@Autowired
	private IOperateLogService operateLogService;


	@Override
	public void afterDelete(Device entity){
		operateLogService.saveLog(EnumLogType.DELETE, EnumOperateFunction.DEVICE, new LogContentBean(entity.getCode()));
		this.removeFromCache(entity.getCode());
	}
	@Override
	public boolean beforeDelete(Device entity){
/*		LambdaQueryWrapper<DeviceChannel> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(DeviceChannel::getDeviceId,entity.getId());
		if (deviceChannelService.getOne(wrapper,false) != null){
			//此设备有通道记录，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_CHANNEL);
		}

		LambdaQueryWrapper<DeviceLog> deviceLogWrapper = new LambdaQueryWrapper<>();
		deviceLogWrapper.eq(DeviceLog::getDeviceId,entity.getId());
		if (deviceLogService.getOne(deviceLogWrapper,false) != null){
			//此设备存在日志记录，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_LOG);
		}

		LambdaQueryWrapper<DeviceOnlineTotal> deviceOnlineTotalWrapper = new LambdaQueryWrapper<>();
		deviceOnlineTotalWrapper.eq(DeviceOnlineTotal::getDeviceId,entity.getId());
		if (deviceOnlineTotalService.getOne(deviceOnlineTotalWrapper,false) != null){
			//此设备存在日志记录，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_LOG);
		}*/



/*		LambdaQueryWrapper<DeviceAlarm> deviceAlarmWrapper = new LambdaQueryWrapper<>();
		deviceAlarmWrapper.eq(DeviceAlarm::getDeviceId,entity.getId());
		if (deviceAlarmService.getOne(deviceAlarmWrapper,false) != null){
			//此设备已有SOS报警数据, 不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_SOSALARM);
		}

		LambdaQueryWrapper<FenceAlarm> fenceAlarmWrapper = new LambdaQueryWrapper<>();
		fenceAlarmWrapper.eq(FenceAlarm::getDeviceId,entity.getId());
		if (fenceAlarmService.getOne(fenceAlarmWrapper,false) != null){
			//此设备已有围栏报警数据, 不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_FENCEALARM);
		}

		LambdaQueryWrapper<DeviceFavorite> deviceFavoriteWrapper = new LambdaQueryWrapper<>();
		deviceFavoriteWrapper.eq(DeviceFavorite::getDeviceId,entity.getId());
		if (deviceFavoriteService.getOne(deviceFavoriteWrapper,false) != null){
			//此设备已被收藏, 不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_FAVOREITE);
		}*/

		LambdaQueryWrapper<Document> dcocumentWrapper = new LambdaQueryWrapper<>();
		dcocumentWrapper.eq(Document::getDeviceId,entity.getId());
		if (documentService.getOne(dcocumentWrapper,false) != null){
			//此设备已有视频文件在用, 不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_DEVICE_USED_BY_DCOUMENT);
		}
		return true;
	}
	@Override
	public boolean beforeUpdate(Device entity){
		QueryWrapper<Device> wrapper = new QueryWrapper<Device>()
				.eq("code", entity.getCode()).ne("id", entity.getId());
		if (this.getOne(wrapper, true) != null){
			log.error(">>>>>> {}",String.format(ExceptionMsg.ERROR_PARAM_DEVICE_EXISTS.getDesc(),entity.getCode()));
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_PARAM_DEVICE_EXISTS,entity.getCode());
		}
		entity.setUpdateTime(new Date());
		return true;

	}
	@Override
	public boolean beforeSave(Device entity){
		if (this.getOne(new QueryWrapper<Device>().eq("code",entity.getCode()), true) != null){
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_PARAM_DEVICE_EXISTS,entity.getCode());
		}
		return true;
	}
	@Override
	public List<Map<String, Object>> countDevices() {
		return getBaseMapper().countDevices();
	}

	/**
	 * 所有注册的联网执法仪
	 * @param queryWrapper
	 * @return
	 */
	@Override
	public
	List<ChartDataBean> countAll(Wrapper queryWrapper){
		return getBaseMapper().countAll(queryWrapper);
	}

	/**
	 * 按部门统计
	 * @param queryWrapper
	 * @return
	 */
	@Override
	public List<ChartDataBean> countByOrg(Wrapper queryWrapper){
		List<ChartDataBean> list = getBaseMapper().countByOrg(queryWrapper);
		List<ChartDataBean> newList=new ArrayList<>();
		ChartDataBean otherChartDataBean = new ChartDataBean().setLongId(-99L).setName("msg_other").setValue(0);
		for (int i=0;i<list.size();i++){
			if (i>=3){
				otherChartDataBean.setValue(otherChartDataBean.getValue()+list.get(i).getValue());
			}else{
				newList.add(list.get(i));
			}
		}
		if (newList.size() < 3){
			PermissionGrade permissionGrade = permissionGradeUtil.getPmGrade();
			if (permissionGrade.getPermissionLevel() >= 3){
				QueryWrapper<Organization> organizationQueryWrapper = new QueryWrapper<>();
				organizationQueryWrapper.likeRight("path",permissionGrade.getOrgPath());
				List<Organization> orgList = organizationService.list(organizationQueryWrapper);
				for(Organization organization : orgList ){
					if (newList.size() >= 3){
						break;
					}
					newList.add(new ChartDataBean().setLongId(organization.getId())
							.setName(organization.getShortName()).setValue(0)
					);
				}
			}else{
				log.info(">>>>>>>>>> countByOrg() 没有查询其它单的权限！");
			}
		}
		newList.add(otherChartDataBean);


		return newList;
	}
	/**
	 * 按类型统计注册数量
	 * @param queryWrapper
	 * @return
	 */
	@Override
	public List<ChartDataBean> countByType(Wrapper queryWrapper){
		List<ChartDataBean> list = getBaseMapper().countByType(queryWrapper);

		List<ChartDataBean> newlist = new ArrayList<>();
		newlist.add(new ChartDataBean().setIntId(1).setName(DeviceType.getByCode(1).getDesc()).setValue(0));
		newlist.add(new ChartDataBean().setIntId(2).setName(DeviceType.getByCode(2).getDesc()).setValue(0));
		newlist.add(new ChartDataBean().setIntId(3).setName(DeviceType.getByCode(3).getDesc()).setValue(0));
		newlist.add(new ChartDataBean().setIntId(6).setName(DeviceType.getByCode(6).getDesc()).setValue(0));
		//合并 为其它类型
		for(int i=0;i<list.size();i++){
			if (list.get(i).getIntId() > 3){
				ChartDataBean chartDataBean6 = newlist.get(3);
				chartDataBean6.setValue(chartDataBean6.getValue() + list.get(i).getValue());
			}else{
				ChartDataBean chartDataBean123 = newlist.get(i);
				chartDataBean123.setValue(chartDataBean123.getValue() + list.get(i).getValue());
			}
		}
		list=null;
		return newlist;
	}
	/**
	 * 设备固件升级
	 * @param device
	 * @return
	 */
	@Override
	public Result firmwareUpdgrade(Device device){
		String host = "http://%s:%s";
		String url=null;

		//判断服务器是否在线
		if (device.getGbServerId() == null){
			log.error("没有设置 国标服务器") ;
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_NOT_BIND_SERVER_EXISTS);
		}

		url = GbServerUtil.get();
		if (url == null){
			GbServer server = gbServerService.getOne(
					new QueryWrapper<GbServer>().eq("online", 1).eq("id",device.getGbServerId()),
					false);
			if (server == null){
				log.error(ExceptionMsg.ERROR_NOT_ONLINE_SERVER_EXISTS.getDesc()) ;
				throw ExceptionUtil.commonException(ExceptionMsg.ERROR_NOT_ONLINE_SERVER_EXISTS);
			}
			url = String.format("http://%s:%s",server.getHost(),server.getApiPort());
		}
		try{

			UpgradeParam param = new UpgradeParam();
			param.setDeviceCode(device.getCode());
			param.setFileUrl("http://119.23.161.197:81/OTA_update/Shengchengshun/DSJ-X2/GZDW/msm8953_64-ota-eng.frank.zip");
			param.setSn((int) ((Math.random() * 9 + 1) * 100000));

			Result result =  deviceApi.deviceFirmwareUpdgrade(url,param);
			return result;
		}catch (Exception e){
			log.error(String.format("给设备 %s 发送升级指令失败: %s",device.getCode(),e.toString())) ;
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_SEND_CAMMAND_TO_DEVICE_FAILED);
		}
	}

	/**
	 * 生成4G执法仪的通道
	 * @param device
	 * @return
	 */
	private DeviceChannel gen4gDeviceChannel(Device device){
		if (device.getCate() !=2){
			return null;
		}
		//4g执法仪, 自动更新通道表
		QueryWrapper<DeviceChannel> wrapper = new QueryWrapper<>();
		wrapper.eq("device_id",device.getId());
		wrapper.eq("channel_type",1); //视频通道
		DeviceChannel deviceChannel = deviceChannelService.getOne(wrapper,false);
		if (deviceChannel == null){
			deviceChannel = new DeviceChannel();
			deviceChannel.setDeviceId(device.getId());
			deviceChannel.setDeviceCode(device.getCode());
			deviceChannel.setChannelCode(device.getDefaultChannel());
			deviceChannel.setName(device.getDefaultChannel());
			deviceChannel.setStatus(0);
			deviceChannel.setCreateTime(new Date());
			deviceChannel.setUpdateTime(new Date());
			deviceChannel.setHasAudio(false);
			//deviceChannelService.save(deviceChannel);
		}else{
			deviceChannel.setDeviceCode(device.getCode());
			deviceChannel.setChannelCode(device.getDefaultChannel());
			deviceChannel.setName(device.getDefaultChannel());
			deviceChannel.setUpdateTime(new Date());
			//deviceChannelService.saveOrUpdate(deviceChannel);
		}
		return deviceChannel;
	}
	@Override
	public List<Device> getAllFromCache() {
		List<Device> list = new ArrayList<>();

		Map<Object,Object> map = sysCache.hmget(Constant.CACHE_KEY_CAMERA_DEVICES);
		if (map != null){
		for(Map.Entry<Object,Object> item: map.entrySet()){
			list.add((Device) item.getValue());
		}}
		return list;

	}


	@Override
	public Device getDeviceFromCache(String code) {
		Object obj = sysCache.hget(Constant.CACHE_KEY_CAMERA_DEVICES, code);
		if (obj != null) {
			return (Device)obj;
		}
		return null;

	}
	@Override
	public Device getFromCache(String deviceCode) {
		return (Device)sysCache.hget(Constant.CACHE_KEY_CAMERA_DEVICES,deviceCode);
	}
	private List<Device> getInfo_back(List<Device> devices){
		List<Long> ids = new ArrayList<Long>();
		/** Organization */
		for(Device d  : devices){
			if (d.getOrgId() != null && !ids.contains(d.getOrgId())){
				ids.add(d.getOrgId() );
			}
		}
		if (ids.size() > 0){
			List<Organization>  list = organizationMapper.selectBatchIds(ids);
			for (Organization o : list){
				for(Device origin : devices){
					if (o.getId().equals(origin.getOrgId())){
						//origin.setOrganization(o);
					}
				}
			}
		}
		/** User */
		ids.clear();
		for(Device d  : devices){
			if (d.getUserId() != null && !ids.contains(d.getUserId())){
				ids.add(d.getUserId() );
			}
		}
		if (ids.size() > 0){
			List<User>  list = userMapper.selectBatchIds(ids);
			for (User o : list){
				for(Device origin : devices){
					if (o.getId().equals(origin.getUserId())){
						//origin.setUser(o);
					}
				}
			}
		}
		/** GbServer */
		ids.clear();
		for(Device d  : devices){
			if (d.getType() == 1){continue;}
			if (d.getGbServerId() != null && !ids.contains(d.getGbServerId())){
				ids.add(d.getGbServerId() );
			}
		}
		if (ids.size() > 0){
			List<GbServer>  list = gbServerMapper.selectBatchIds(ids);
			for (GbServer o : list){
				for(Device origin : devices){
					if (o.getId().equals(origin.getGbServerId())){
						//origin.setGbServer(o);
					}
				}
			}
		}


/*		*//** online *//*
		List<String> codeList = new ArrayList<String>();
		for(Device d  : devices){
			if (d.getType() == 1){continue;}
			if (d.getCode() != null && !codeList.contains(d.getCode())){
				codeList.add(d.getCode());
			}
		}
		if (codeList.size() > 0){
			String codes="";
			for(String s : codeList){
				if (StringUtils.isEmpty(codes)){
					codes = "'" + s + "'" ;
				}else{
					codes = codes + "," + "'" + s +"'"  ;
				}
			}
			codes = "(" + codes + ")";

			List<Device>  list = this.getBaseMapper().getOnlineStatusFromOtherDevice(codes);
			for (Device d : list){
				for(Device origin : devices){
					if (d.getCode().equals(origin.getCode())){
						if (!StringUtils.isEmpty(d.getNote()) && d.getNote().equals("1") )
							origin.setOnline(true);
					}
				}
			}
		}*/

		return devices;
	}

	/**
	 * 是否报警通道，判断标准备，ID 含134，通道名含 Alarm
	 * @param remoteChannel
	 * @return
	 */
	private boolean isAlarmChn(GbDeviceChannelResult remoteChannel){
		boolean isAlarmChn = false;
		isAlarmChn = remoteChannel.getChannelId().length() >= 13 && remoteChannel.getChannelId().indexOf("134")==9?true:false;
		if (!isAlarmChn){
			if (!StringUtils.isEmpty(remoteChannel.getName())){
				if (remoteChannel.getName().toUpperCase().startsWith("ALARM")){
					return true;
				}
			}
		}
		return isAlarmChn;
	}


    /**
     * 查询列表
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
	@Override
	public List<Device> list(Wrapper<Device> queryWrapper) {
		List<Device> devices = getBaseMapper().selectList(queryWrapper);
        return devices;
		//return getInfo(devices);
    }

	/**
	 * 加新的通道
	 * @param remoteChn
	 * @param device
	 */
	private void newChannel(GbDeviceChannelResult remoteChn,Device device){
		DeviceChannel deviceChannel =  new DeviceChannel();
		deviceChannel.setCreateTime(new Date());
		deviceChannel.setDeviceId(device.getId());
		this.updateFields(remoteChn,deviceChannel);
		deviceChannelService.save(deviceChannel);
	}

    /**
     * 翻页查询
     *
     * @param page         翻页对象
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
/*	@Override
	public <E extends IPage<Device>> E page(E page, Wrapper<Device> queryWrapper) {
		E e = getBaseMapper().selectPage(page, queryWrapper);
		e.setRecords(getInfo(e.getRecords()));
		return e;
    }*/

	/**
	 * 根据 ID 选择修改
	 *
	 * @param entity 实体对象
	 */
	@Override
	@Transactional
	public boolean updateById(Device entity) {
		entity.setSynch(false);
		if (!super.updateById(entity)){return false;}

		//执法仪则生成新默认的通道号到通道表中
/*		if (entity.getCate() == 2){
			DeviceChannel deviceChannel = this.gen4gDeviceChannel(entity);
			deviceChannelService.saveOrUpdate(deviceChannel);
		}*/

		//清空单位
		if (entity.getOrgId() == null){
			UpdateWrapper<Device> updateWrapper = new UpdateWrapper();
			updateWrapper.set("org_id",null);
			updateWrapper.eq("id",entity.getId());
			this.update(updateWrapper);
		}

		if (entity.getCate() == 2){
			DeviceChannel deviceChannel = this.gen4gDeviceChannel(entity);
			if (deviceChannel != null){
				deviceChannelService.saveOrUpdate(deviceChannel);
				//entityOperateLogService.saveLog(deviceChannel,"DeviceChannel","ADD");
			}
		}

		this.saveToCache(entity);

		//更新到国标服务器
		this.updateDeviceToGbServer(entity);


		//entityOperateLogService.saveLog(entity,"Device","EDIT");
		operateLogService.saveLog(EnumLogType.EDIT, EnumOperateFunction.DEVICE,new LogContentBean(entity.getCode()));
		return true;
	}
	/**
	 * 更新现有的通道
	 * @param remoteChn
	 * @param localChn
	 */
	private void updateChanel(GbDeviceChannelResult remoteChn,DeviceChannel localChn){
		localChn.setUpdateTime(new Date());
		this.updateFields(remoteChn,localChn);
		deviceChannelService.updateById(localChn);
	}
	/**
	 * 更新设备信息到国标服务器
	 * @param device
	 */
	@Override
	public void updateDeviceToGbServer(Device device)  {
		//判断服务器是否在线
		if (device.getGbServerId() == null){
			return;
		}

		GbServer gbServer = gbServerService.getFromCache(device.getGbServerId().toString());

/*		QueryWrapper<GbServerParam> gbWrapper = new QueryWrapper<>();
		gbWrapper.eq("s.online", 1).eq("s.id",device.getGbServerId());
		GbServerBean gbServerBean = gbServerService.getOneInfo(gbWrapper,false);*/
		if (gbServer == null){
			log.error(">>>>>>>> 设备信息更新到国标服务器失败，国标服务器不在线！>>>>>>>>>>>>");
			return;
		}

		GbDevice gbDevice = new GbDevice();
		gbDevice.setHasAudio(device.getHasAudio());
		gbDevice.setDeviceId(device.getCode());
		gbDevice.setStreamMode(EnumStreamMode.UDP.name()); //UDP协议
		if (!StringUtils.isEmpty(device.getStreamMode())){
			if (EnumStreamMode.TCP_ACTIVE.name().equals(device.getStreamMode())) {
				gbDevice.setStreamMode("TCP-ACTIVE");
			}else if (EnumStreamMode.TCP_PASSIVE.name().equals(device.getStreamMode())){
				gbDevice.setStreamMode("TCP-PASSIVE");
			}
		}


		//GPS信息订阅
		gbDevice.setSubscribeCycleForMobilePosition(0);
		gbDevice.setMobilePositionSubmissionInterval(5);
		if (device.getSubscriberPosition() > 0){
			gbDevice.setSubscribeCycleForMobilePosition(600);
		}
		if (null != device.getSubscriberPositionInterval() && device.getSubscriberPositionInterval()>5){
			gbDevice.setMobilePositionSubmissionInterval(device.getSubscriberPositionInterval());
		}

		//报警订阅
		gbDevice.setSubscribeCycleForAlarm(0);
		if (device.getSubscriberAlarm()>0){
			gbDevice.setSubscribeCycleForAlarm(600);
		}
		//订阅目录
		gbDevice.setSubscribeCycleForCatalog(0);
		if (device.getSubscriberCatalog()>0){
			gbDevice.setSubscribeCycleForCatalog(600);
		}

		if (!StringUtils.isEmpty(device.getName())){
			gbDevice.setName(device.getName());
		}
		gbDevice.setGeoCoordSys("WGS84");
		if (!StringUtils.isEmpty(device.getCoordinateSystem())){
			gbDevice.setGeoCoordSys(device.getCoordinateSystem());
		}
		//gbDevice.setStreamMode(device.getStreamMode());
		try{
			Future<Result> fResult = deviceUpdateToGbServerTask.updateToGbSvr(gbDevice,gbServer);
			if (fResult.get().isSuccess()){
				log.info(">>>>>>>> 设备信息更新到国标服务器成功！！>>>>>>>>>>>>");
			}else{
				log.info(">>>>>>>> 设备信息更新到国标服务器失败：{}",fResult.get().getMsg());
			}
		}catch (Exception e){
			log.error(">>>>>>>> 设备信息更新到国标服务器错误：{}",e.toString());
		}
	}
	private void updateFields(GbDeviceChannelResult remoteChn,DeviceChannel deviceChannel){
		deviceChannel.setChannelCode(remoteChn.getChannelId());
		deviceChannel.setName(remoteChn.getName());
		deviceChannel.setManufacture(remoteChn.getManufacture());
		deviceChannel.setModel(remoteChn.getModel());
		deviceChannel.setOwner(remoteChn.getOwner());
		deviceChannel.setBlock(remoteChn.getBlock());
		deviceChannel.setAddress(remoteChn.getAddress());
		deviceChannel.setParentId(remoteChn.getParentId());
		deviceChannel.setSafetyWay(remoteChn.getSafetyWay());
		deviceChannel.setRegisterWay(remoteChn.getRegisterWay());
		deviceChannel.setCertNum(remoteChn.getCertNum());
		deviceChannel.setCertifiable(remoteChn.getCertifiable());
		deviceChannel.setErrCode(remoteChn.getErrCode());
		deviceChannel.setEndTime(remoteChn.getEndTime());
		deviceChannel.setCreateBy(remoteChn.getSecrecy());
		deviceChannel.setIpAddress(remoteChn.getIpAddress());
		deviceChannel.setPort(remoteChn.getPort());
		deviceChannel.setPassword(remoteChn.getPassword());
		deviceChannel.setPtzType(remoteChn.getPTZType());
		deviceChannel.setStatus(remoteChn.getStatus());
		deviceChannel.setLongitude(remoteChn.getLongitude());
		deviceChannel.setLatitude(remoteChn.getLatitude());
		deviceChannel.setStreamId(remoteChn.getStreamId());
		deviceChannel.setDeviceCode(remoteChn.getDeviceId());
		deviceChannel.setParental(String.valueOf(remoteChn.getParental()));
		deviceChannel.setHasAudio(remoteChn.isHasAudio());
		deviceChannel.setChannelType(!this.isAlarmChn(remoteChn)?1:2);
	}
	@Override
	@Transactional
	public boolean remove(Wrapper<Device> queryWrapper) {
		return super.remove(queryWrapper);

/*		List<Device> list = super.list(queryWrapper);

		if (CollectionUtils.isEmpty(list)){return true;}

		List<String> deletedCodes = new ArrayList<>();
		// 先删除关联数据
		for(Device device : list) {
			if (beforeDelete(device)) {
				this.removeRelate(device);
				deletedCodes.add(device.getCode());
			}
		}

		super.remove(queryWrapper);

		for(String code : deletedCodes){
			operateLogService.saveLog(EnumLogType.DELETE, EnumOperateFunction.DEVICE, new LogContentBean(code));
			this.removeFromCache(code);
*//*
			if (device.getCate() == 2){
				//4G 执法仪先删除 通道
				QueryWrapper<DeviceChannel> wrapper = new QueryWrapper<DeviceChannel>().eq("device_id",device.getId());
				DeviceChannel deviceChannel = deviceChannelService.getOne(wrapper,false);
				if (deviceChannel != null){
					deviceChannelService.removeById(deviceChannel.getId());
					//entityOperateLogService.saveLog(deviceChannel,"DeviceChannel","REMOVE");
				}
			}else{
				if (!beforeDelete(device)){return false;}
			}
*//*
		}


		//执法仪删除
		*//*boolean result = false;
		if ((result = super.remove(queryWrapper))==true){
			for(Device device : list){
				//清缓存
				this.removeFromCache(device.getCode());
				//日志
				//entityOperateLogService.saveLog(device,"Device","REMOVE");
				// 操作日志
				//operateLogService.saveLog(EnumLogType.DELETE, EnumOperateFunction.DEVICE,new JSONObject().put("code",device.getCode()));
				operateLogService.saveLog(EnumLogType.DELETE, EnumOperateFunction.DEVICE,new LogContentBean(device.getCode()));
			}
		}*//*


		return true;*/
	}
	@Override
	@Transactional
	public boolean removeById(Serializable id) {
		return super.removeById(id);

		//Device entity = super.getById(id);
/*
		if (entity.getType() == 2){
			//4G 执法仪先删除 通道
			QueryWrapper<DeviceChannel> wrapper = new QueryWrapper<DeviceChannel>().eq("device_id",entity.getId());
			DeviceChannel deviceChannel = deviceChannelService.getOne(wrapper,false);
			if (deviceChannel != null){
				deviceChannelService.removeById(deviceChannel.getId());
				//entityOperateLogService.saveLog(deviceChannel,"DeviceChannel","REMOVE");
			}
		}
*/
/*		else{

		}*/

/*		if (!beforeDelete(entity)){return false;}
		// 先删删除相关联数据： 设备报警/设备通道/设备收藏/设备上下线日志/设备上下线统计/围栏报警
		this.removeRelate(entity);

		boolean result = super.removeById(id);

		this.removeFromCache(entity.getCode());
		//entityOperateLogService.saveLog(entity,"Device","REMOVE");
		operateLogService.saveLog(EnumLogType.DELETE, EnumOperateFunction.DEVICE,new LogContentBean(entity.getCode()));
		return result;*/
	}

	/**
	 * 删除相关联
	 * 设备报警/设备通道/设备收藏/设备上下线日志/设备上下线统计/围栏报警
	 * @param device
	 */
	@Override
	public void removeRelate(Device device){
		//1、设备报警
		LambdaQueryWrapper<DeviceAlarm> alarmWrapper = new LambdaQueryWrapper<>();
		alarmWrapper.eq(DeviceAlarm::getDeviceId,device.getId());
		deviceAlarmService.remove(alarmWrapper);
		//2、设备通道
		LambdaQueryWrapper<DeviceChannel> channelWrapper = new LambdaQueryWrapper<>();
		channelWrapper.eq(DeviceChannel::getDeviceId,device.getId());
		deviceChannelService.remove(channelWrapper);

		//3、设备收藏
		LambdaQueryWrapper<DeviceFavorite> favoriteWrapper = new LambdaQueryWrapper<>();
		favoriteWrapper.eq(DeviceFavorite::getDeviceId,device.getId());
		deviceFavoriteService.remove(favoriteWrapper);
		//4、设备上下线日志
		LambdaQueryWrapper<DeviceLog> logWrapper = new LambdaQueryWrapper<>();
		logWrapper.eq(DeviceLog::getDeviceId,device.getId());
		deviceLogService.remove(logWrapper);

		//5、设备上下线统计
		LambdaQueryWrapper<DeviceOnlineTotal> onlineTotalWrapper = new LambdaQueryWrapper<>();
		onlineTotalWrapper.eq(DeviceOnlineTotal::getDeviceId,device.getId());
		deviceOnlineTotalService.remove(onlineTotalWrapper);
		//6、围栏报警
		LambdaQueryWrapper<FenceAlarm> fenceAlarmWrapper = new LambdaQueryWrapper<>();
		fenceAlarmWrapper.eq(FenceAlarm::getDeviceId,device.getId());
		fenceAlarmService.remove(fenceAlarmWrapper);
	}

	@Override
	public void removeFromCache(String deviceCode){
		sysCache.hdel(Constant.CACHE_KEY_CAMERA_DEVICES, deviceCode);
	}
	@Override
	@Transactional
	public boolean save(Device entity) {
		entity.setOnline(false);
		entity.setSynch(false);
		if (entity.getSubscriberPosition() == null){entity.setSubscriberPosition(0);}
		if (entity.getSubscriberCatalog() == null){entity.setSubscriberCatalog(0);}
		if (entity.getSubscriberAlarm() == null){entity.setSubscriberAlarm(0);}
		if (entity.getSubscriberPositionInterval() == null){entity.setSubscriberPositionInterval(5);}

		entity.setChannelCount(1);

		if (!super.save(entity)){ return false;}

		if (entity.getCate() == 2){
			DeviceChannel deviceChannel = this.gen4gDeviceChannel(entity);
			if (deviceChannel != null){
				deviceChannelService.saveOrUpdate(deviceChannel);
				entityOperateLogService.saveLog(deviceChannel,"DeviceChannel","ADD");
			}
		}

		//保存到缓存
		this.saveToCache(entity);
		//更新到国标服务器
		this.updateDeviceToGbServer(entity);


		operateLogService.saveLog(EnumLogType.ADD, EnumOperateFunction.DEVICE,new LogContentBean(entity.getCode()));

		//entityOperateLogService.saveLog(entity,"Device","ADD");
		return true;
	}
	@Override
	public void saveAllToCache() {
		sysCache.del(Constant.CACHE_KEY_CAMERA_DEVICES);
		QueryWrapper<Device> wrapper = new QueryWrapper<Device>();
		wrapper.eq("cate",2).or().eq("cate",3);
		List<Device> list = getBaseMapper().selectList(wrapper);
		for(Device dev:list){
			this.saveToCache(dev);
		}
	}
	@Override
	public void saveToCache(Device dev) {
		sysCache.hset(Constant.CACHE_KEY_CAMERA_DEVICES, dev.getCode(), dev);
	}
	/**
	 * 处理操作日志
	 * @param device
	 * @param operate
	 */
	private void saveToOperateLog(Device device, String operate){
		EntityOperateLog log = new EntityOperateLog();
		log.setOperate(operate);
		log.setEntityName("Device");
		log.setState(0);
		log.setOperateDate(new Date());
		log.setData(JSON.toJSON(device).toString());
		entityOperateLogService.save(log);
	}

	/**
	 * 上线就同步新通道信息
	 * @param device
	 * @Async 使用会导到循环报错, 这里不能用 @Async
	 */
	@Override
	public void syncDeviceChannel(Device device){
		String host = "http://%s:%s";
		String url=null;

		url = GbServerUtil.get();
		if (url == null){
			if (device.getGbServerId() == null){return;}
			//判断服务器是否在线
			QueryWrapper<GbServer> gbWrapper = new QueryWrapper<>();
			gbWrapper.eq("online", 1).eq("id",device.getGbServerId());
			GbServer sbServer = gbServerService.getOne(gbWrapper,false);
			if (sbServer == null){
				log.error(">>>>>>>> 从国标平同步设备信息失败，国标服务器不在线！>>>>>>>>>>>>");
				return;
			}
			url = String.format(host,sbServer.getHost(),sbServer.getApiPort());
		}

		try{
			Result result =  deviceApi.queryDeviceChannelByDeviceId(url,new GbDeviceChannel(device.getCode()));
			if (result.getCode() != 0){return;}
			Result result1=JSON.parseObject(result.getData().toString(),Result.class);
			if (result1.getCode() != 0){return;}
			//System.out.println(result1.getData().toString());
			List<GbDeviceChannelResult> remoteChnList = JSON.parseObject(result1.getData().toString(),List.class);
			//查询本的通道列表
			QueryWrapper<DeviceChannel> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("device_id",device.getId());
			List<DeviceChannel> localChnList = deviceChannelService.list(queryWrapper);
			for(DeviceChannel dc:localChnList){dc.setSynch(false);}
			int chnCount = 0;
			String defaultChannel=null; //第一个默认的
			String defaultAlarmChannel=null; //第一个默认的
			if (!CollectionUtils.isEmpty(remoteChnList)){
				boolean exited = false;
				GbDeviceChannelResult remoteChn = null;
				for(Object obj : remoteChnList){
					remoteChn = JSON.parseObject(obj.toString(),GbDeviceChannelResult.class);
					exited = false;
					for(DeviceChannel localChn : localChnList){
						if (remoteChn.getChannelId().equals(localChn.getChannelCode())){
							exited = true;
							localChn.setSynch(true);
							//更新原通道
							this.updateChanel(remoteChn,localChn);
							break;
						}
					}
					if (!this.isAlarmChn(remoteChn)){
						//非报警通道
						chnCount++;
						if (StringUtils.isEmpty(defaultChannel)){defaultChannel = remoteChn.getChannelId();}
					}else{
						if (StringUtils.isEmpty(defaultAlarmChannel)){defaultAlarmChannel = remoteChn.getChannelId();}
					}

					if (!exited){
						//新的
						this.newChannel(remoteChn,device);
					}
				}
				//更新设备的通道数及默认视频通道和报警通道
				device.setChannelCount(chnCount);
				device.setDefaultChannel(defaultChannel);
				device.setDefaultAlarmChannel(StringUtils.isEmpty(defaultAlarmChannel)?defaultChannel:defaultAlarmChannel);
				this.saveToCache(device);

				UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
				deviceUpdateWrapper.set("channel_count",chnCount);
				deviceUpdateWrapper.set("default_channel",defaultChannel);
				deviceUpdateWrapper.set("default_alarm_channel",device.getDefaultAlarmChannel());
				deviceUpdateWrapper.eq("id",device.getId());
				this.update(deviceUpdateWrapper);

				//只有一个通道的全部置为在线
				if (chnCount <= 1){
					UpdateWrapper<DeviceChannel> deviceChannelUpdateWrapper = new UpdateWrapper<>();
					deviceChannelUpdateWrapper.set("status",1);
					deviceChannelUpdateWrapper.eq("device_id",device.getId());
					deviceChannelService.update(deviceChannelUpdateWrapper);
				}
			}
			for(DeviceChannel dc:localChnList){
				//远程服务器上没有的要删除
				if (!dc.getSynch()){
					deviceChannelService.removeById(dc.getId());
				}
			}

		}catch (Exception e){
			log.error(">>>>>>>> 更新通道号错误： {}",e.toString());
		}
	}


}
